/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  PropertyAnalysis, TypeStructure, TypeDependency, PropertyDecorators, DependencySource,
  TypeDetails, EnumDetails, EnumMemberInfo, ClassDetails, InterfaceDetails, TypeAliasDetails
} from '..';

export class DeepCopyUtil {
  static copyPropertyAnalysis(original: PropertyAnalysis): PropertyAnalysis {
    return {
      name: original.name,
      defaultValue: original.defaultValue,
      decorators: this.copyPropertyDecorators(original.decorators),
      isMust: original.isMust,
      type: this.copyTypeStructure(original.type),
      visibility: original.visibility
    };
  }

  private static copyPropertyDecorators(original?: PropertyDecorators): PropertyDecorators | undefined {
    if (!original) {
      return undefined;
    }
    return {
      serialName: original.serialName,
      isRequired: original.isRequired,
      isTransient: original.isTransient,
      isPlainValue: original.isPlainValue,
      with: original.with
    };
  }

  static copyTypeStructure(original: TypeStructure): TypeStructure {
    const copy: TypeStructure = {
      kind: original.kind,
      depth: original.depth,
      sourceText: original.sourceText,
      args: [], // 初始化为空数组，后面会根据原始值拷贝
      dependencies: this.copyTypeDependencies(original.dependencies)
    };

    // 深拷贝枚举详细信息
    if (original.enumDetails) {
      copy.enumDetails = this.copyEnumDetails(original.enumDetails);
    }

    // 深拷贝类详细信息
    if (original.classDetails) {
      copy.classDetails = this.copyClassDetails(original.classDetails);
    }

    if (original.unionDetails) {
      copy.unionDetails = original.unionDetails.map(
        member => this.copyTypeStructure(member)
      );
    }

    if (original.args && original.args.length > 0) {
      copy.args = original.args.map(
        arg => this.copyTypeStructure(arg)
      );
    }

    return copy;
  }

  static copyTypeDependencies(original: TypeDependency[]): TypeDependency[] {
    return original.map(dependency => this.copyTypeDependency(dependency));
  }

  private static copyTypeDependency(original: TypeDependency): TypeDependency {
    const copy: TypeDependency = {
      typeName: original.typeName,
      typeKind: original.typeKind,
      importPath: original.importPath,
      source: this.copyDependencySource(original.source)
    };

    // 深拷贝详细信息（如果存在）
    if (original.details) {
      copy.details = this.copyTypeDetails(original.details);
    }

    return copy;
  }

  private static copyDependencySource(original: DependencySource): DependencySource {
    return {
      type: original.type,
      sourceFilePath: original.sourceFilePath,
      originalImport: original.originalImport,
      packageName: original.packageName
    };
  }

  private static copyTypeDetails(original: TypeDetails): TypeDetails {
    // TypeDetails 是联合类型，需要根据 kind 分别处理
    switch (original.kind) {
      case 'enum':
        return this.copyEnumDetails(original);
      case 'class':
        return this.copyClassDetails(original);
      case 'interface':
        return this.copyInterfaceDetails(original);
      case 'type':
        return this.copyTypeAliasDetails(original);
      default:
        // 默认浅拷贝未知类型
        return { ...original };
    }
  }

  private static copyEnumDetails(original: EnumDetails): EnumDetails {
    return {
      kind: original.kind,
      members: original.members ? original.members.map((member: EnumMemberInfo) => ({
        name: member.name,
        value: member.value,
        literalValue: member.literalValue
      })) : [],
      valueType: original.valueType
    };
  }

  private static copyClassDetails(original: ClassDetails): ClassDetails {
    return {
      kind: original.kind,
      classDecl: original.classDecl,
      isGeneric: original.isGeneric
    };
  }

  private static copyInterfaceDetails(original: InterfaceDetails): InterfaceDetails {
    return {
      kind: original.kind,
      interfaceDecl: original.interfaceDecl,
      isGeneric: original.isGeneric
    };
  }

  private static copyTypeAliasDetails(original: TypeAliasDetails): TypeAliasDetails {
    return {
      kind: original.kind,
      aliasedType: original.aliasedType,
      resolvedType: this.copyTypeStructure(original.resolvedType!)
    };
  }

  static deepCopy<T>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
      return obj;
    }

    if (obj instanceof Date) {
      return new Date(obj.getTime()) as unknown as T;
    }

    if (obj instanceof Array) {
      return obj.map(item => this.deepCopy(item)) as unknown as T;
    }

    if (typeof obj === 'object') {
      const copy: any = {};
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          copy[key] = this.deepCopy((obj as any)[key]);
        }
      }
      return copy as T;
    }

    return obj;
  }
}